let voxTimes = 0;
const VOXEL_BUILD_TIMES = 10;
const offLight_voxel = 'navajo_white';
const onLight_voxel = 'warm_yellow_light';
function camera(
    entity: GamePlayerEntity,
    x: number,
    y: number,
    z: number,
    dis: number
) {
    return new Promise((resolve) => {
        entity.player.cameraMode = GameCameraMode.FIXED;
        entity.player.cameraPosition = new GameVector3(x, y, z);
        entity.player.cameraTarget = new GameVector3(x, y, z);

        const d = dis;
        let yaw = 0;
        const interval = setInterval(() => {
            yaw += 0.07;
            entity.player.cameraPosition = new GameVector3(
                Math.sin(yaw) * d + 127,
                100,
                Math.cos(yaw) * d + 127
            );

            if (yaw >= Math.PI * 4) {
                clearInterval(interval);
                resolve();
            }
        }, 64);
    });
}

/**
 * 更改背景音乐
 * @param {string} name - 音乐文件名
 */
async function change_music(name: GameAudioAssets) {
    for (let i = Math.floor(world.ambientSound.gain); i > 0; i -= 0.03) {
        world.ambientSound.gain = i;
        await sleep(64);
    }
    world.ambientSound.gain = 0;
    world.ambientSound.sample = name;
    for (let i = 0; i < 1; i += 0.03) {
        world.ambientSound.gain = i;
        await sleep(64);
    }
}
async function closeMusic() {
    for (let i = Math.floor(world.ambientSound.gain); i > 0; i -= 0.03) {
        world.ambientSound.gain = i;
        await sleep(64);
    }
    world.ambientSound.gain = 0;
}
async function moon(bool = true) {
    const getVoxel = bool ? offLight_voxel : onLight_voxel;
    const setVoxel = bool ? onLight_voxel : offLight_voxel;
    for (let y = 23; y <= 38; y++) {
        for (let z = 118; z <= 135; z++) {
            if (voxels.name(voxels.getVoxelId(175, y, z)) === getVoxel) {
                voxels.setVoxel(175, y, z, setVoxel);
            }
        }
    }
}

let allLightVox: GameVector3[] = [];
// let index = 0;
for (let x = 0; x <= 256; x++) {
    for (let y = 0; y <= 64; y++) {
        for (let z = 0; z <= 256; z++) {
            /* 不在月亮区域内*/
            if (
                voxels.name(voxels.getVoxelId(x, y, z)) ===
                    'warm_yellow_light' &&
                !(x === 175 && y >= 23 && y <= 38 && z >= 118 && z <= 135)
            ) {
                allLightVox.push(new GameVector3(x, y, z));
                // index++;
            }
        }
    }
}
function sort1() {
    allLightVox = allLightVox.sort((a, b) => {
        const posa = new GameVector3(a.x, a.y, a.z);
        const posb = new GameVector3(b.x, b.y, b.z);
        const startPos = new GameVector3(64, 8, 64);
        return startPos.distance(posa) - startPos.distance(posb);
    });
}
function sort2() {
    allLightVox = allLightVox.sort((a, b) => {
        return a.x - b.x || a.y - b.y || a.z - b.z;
    });
}

// 播放动画
async function offLight(ani = true) {
    sort1();

    for (const p of allLightVox) {
        voxels.setVoxel(p.x, p.y, p.z, offLight_voxel);
        // p.state = false;
        voxTimes++;
        if (voxTimes % VOXEL_BUILD_TIMES === 0 && ani) {
            await sleep(64);
        }
    }
}
async function onLight(ani = true) {
    sort1();

    for (const p of allLightVox) {
        voxels.setVoxel(p.x, p.y, p.z, onLight_voxel);
        // p.state = true;
        voxTimes++;
        if (voxTimes % VOXEL_BUILD_TIMES === 0 && ani) {
            await sleep(64);
        }
    }
}

const tx = world.addZone({
    selector: '.blind',
    bounds: new GameBounds3(
        new GameVector3(0, 0, 0),
        new GameVector3(300, 300, 300)
    ),

    fogEnabled: true,
    fogColor: new GameRGBColor(0, 0, 0),
    // fogStartDistance: 50,
    fogHeightOffset: 25,
    fogMax: 1,
    fogDensity: -10,
});

// 雾气
function fogOn() {
    world.querySelectorAll('player').forEach((e) => {
        e.addTag('blind');
    });
}
function fogOff() {
    world.querySelectorAll('player').forEach((e) => {
        e.removeTag('blind');
    });
}
// 随机点亮
async function randomLight_1(times: number) {
    sort1();
    let voxelsPos1 = [];
    let voxelsPos2 = [];
    for (let i = 0; i < times; i++) {
        voxelsPos2 = [...voxelsPos1];
        voxelsPos1 = [];
        for (const e of voxelsPos2) {
            voxels.setVoxel(e.x, e.y, e.z, offLight_voxel);
        }
        for (const p of allLightVox) {
            const randomN = Math.random() > 0.8;
            if (randomN) {
                voxels.setVoxel(p.x, p.y, p.z, onLight_voxel);
                voxelsPos1.push(new GameVector3(p.x, p.y, p.z));
                voxTimes++;
                if (voxTimes % 30 === 0 && randomN) {
                    // await sleep(64);
                }
            }
        }
        await sleep(800);
    }
}
// 逐一显示，注意这个需要改排序，改成相见
async function randomLight_2() {
    sort2();
    for (let i = 0; i < allLightVox.length - 1; i += VOXEL_BUILD_TIMES) {
        for (
            let j = 0;
            j < Math.min(allLightVox.length - 1 - i, VOXEL_BUILD_TIMES);
            j++
        ) {
            const p = allLightVox[i + j];
            voxels.setVoxel(p.x, p.y, p.z, onLight_voxel);
            // p.state = true;
        }
        await sleep(100);
        for (
            let j = 0;
            j < Math.min(allLightVox.length - 1 - i, VOXEL_BUILD_TIMES);
            j++
        ) {
            const p = allLightVox[i + j];
            voxels.setVoxel(p.x, p.y, p.z, offLight_voxel);
            // p.state = true;
        }
    }
}

// 楼梯点亮效果
async function onStairs() {
    for (let x = 171; x >= 135; x--) {
        for (let z = 126; z <= 128; z++) {
            voxels.setVoxel(
                x,
                22 - Math.floor((171 - x) / 4),
                z,
                onLight_voxel
            );
            tx.fogHeightOffset = 22 - (171 - x) / 4;
        }
        if ((171 - x) % 4 === 0) {
            await sleep(1200);
        }
    }
}
async function closeStairs() {
    for (let x = 135; x <= 171; x++) {
        for (let z = 126; z <= 128; z++) {
            voxels.setVoxel(
                x,
                22 - Math.floor((171 - x) / 4),
                z,
                offLight_voxel
            );
        }
        if ((171 - x) % 4 === 0) {
            await sleep(100);
        }
    }
}

let state = false;
async function light_show() {
    if (state) {
        return;
    }
    state = true;
    await sleep(2000);
    change_music('audio/创作节中场灯光秀配乐.mp3');
    world.say('超级灯光秀即将开始，眼前将会有怎样的场景呢？');
    world.lightMode = 'manual';
    offLight();
    for (let i = 3; i >= 0.5; i -= 0.1) {
        world.sunLight = new GameRGBColor(i, i, i);
        await sleep(64);
    }
    moon(true);
    world.sunLight = new GameRGBColor(0.5, 0.5, 0.5);
    await sleep(15 * 1000);
    moon(false);
    for (let i = 0; i < 3; i++) {
        await randomLight_2();
    }
    await randomLight_1(25);
    await sleep(3000);
    fogOn();
    moon(true);
    await sleep(2000);
    for (let i = 0; i <= 22; i += 0.1) {
        tx.fogHeightOffset = i;
        await sleep(64);
    }
    await onStairs();
    await sleep(2000);
    closeStairs();
    fogOff();
    for (let i = 0; i < 3; i++) {
        await onLight(false);
        await sleep(2000);
        await offLight(false);
        await sleep(2000);
    }
    await sleep(4000);
    await onLight();
    for (let i = 0.5; i <= 3; i += 0.1) {
        world.sunLight = new GameRGBColor(i, i, i);
        await sleep(64);
    }
    world.lightMode = 'natural';

    closeMusic();
    state = false;
}

export { light_show, offLight, onLight, closeMusic, change_music };
